1 import sys, random
2
3 if
sys.version_info.major > 2:
4     import tkinter
as tk
5 else
:
6     import Tkinter
as tk
7
8 GREEN, BLACK, WHITE, DARK_GREEN, BLUE =
"green", "black", "white", "dark green", "blue"
9 ZERO =
2
10 LOWER, UPPER =
"lower", "upper"
11 HOME, AWAY =
"Player 1", "Player 2"
12 START_SCORE = {HOME:
0, AWAY: 0}
13 MAX_SCORE =
7
14 SPEED =
20
15 FONT =
"ms 50"
16 MAX_SPEED, PADDLE_SPEED =
15, 15
17
18
19 def str_dict(dic):
20     
return "%s: %d, %s: %d" % (HOME, dic[HOME], AWAY, dic[AWAY])
21     
22 def rand():
23     
return random.choice(((1, 1), (1, -1), (-1, 1), (-1, -1)))
24     
25
26         

27 class
Equitment(object):
28     def __init__(self, canvas, width, position, color):
29         self.can, self.w = canvas, width
30         self.x, self.y = position
31         
32         self.Object = self.can.create_oval(self.x-self.w, self.y-self.w,
33                                     self.x+self.w, self.y+self.w, fill=color)
34     def update(self, position):
35         self.x, self.y = position
36         self.can.coords(self.Object, self.x-self.w, self.y-self.w,
37                                      self.x+self.w, self.y+self.w)
38     def __eq__(self, other):
39         overlapping = self.can.find_overlapping(self.x-self.w, self.y-self.w,
40                                                 self.x+self.w, self.y+self.w)
41         
return other.get_object() in overlapping
42         
43     def get_width(self):
44         
return self.w
45     def get_position(self):
46         
return self.x, self.y
47     def get_object(self):
48         
return self.Object
49         

50 class
PuckManager(Equitment):
51     def __init__(self, canvas, width, position):
52         Equitment.__init__(self, canvas, width, position, BLACK)
53         

54 class
Paddle(Equitment):
55     def __init__(self, canvas, width, position):
56         Equitment.__init__(self, canvas, width, position, GREEN)
57         self.handle = self.can.create_oval(self.x-self.w/
2, self.y-self.w/2,
58                                 self.x+self.w/
2, self.y+self.w/2, fill=DARK_GREEN)
59     def update(self, position):
60         Equitment.update(self, position)
61         self.can.coords(self.handle, self.x-self.w/
2, self.y-self.w/2,
62                                    self.x+self.w/
2, self.y+self.w/2)
63                                    

64 class
Background(object):
65     def __init__(self, canvas, screen, goal_w):
66         self.can, self.goal_w = canvas, goal_w
67         self.w, self.h = screen
68         
69         self.draw_bg()
70     
71     def draw_bg(self):
72         self.can.config(bg=WHITE, width=self.w, height=self.h)
73         d = self.goal_w/
4
74         self.can.create_oval(self.w/
2-d, self.h/2-d, self.w/2+d, self.h/2+d,
75                                                      fill=WHITE, outline=BLUE)
76         self.can.create_line(ZERO, self.h/
2, self.w, self.h/2, fill=BLUE)
77         self.can.create_line(ZERO, ZERO, ZERO, self.h, fill=BLUE)
78         self.can.create_line(self.w, ZERO, self.w, self.h, fill=BLUE)
79     
80         self.can.create_line(ZERO, ZERO, self.w/
2-self.goal_w/2, ZERO,
81                                                                      fill=BLUE)
82         self.can.create_line(self.w/
2+self.goal_w/2, ZERO, self.w, ZERO,
83                                                                      fill=BLUE)
84         
85         self.can.create_line(ZERO, self.h, self.w/
2-self.goal_w/2, self.h,
86                                                                      fill=BLUE)
87         self.can.create_line(self.w/
2+self.goal_w/2, self.h, self.w, self.h,
88                                                                      fill=BLUE)
89                                                                      
90     def is_position_valid(self, position, width, constraint=None):
91         x, y = position
92
93         
if constraint == None and self.is_in_goal(position, width):
94             
return True
95         elif (x - width < ZERO or x + width > self.w or
96             y - width < ZERO or y + width > self.h):
97             
return False
98         elif constraint == LOWER:
99             
return y - width > self.h/2
100         elif constraint == UPPER:
101             
return y + width < self.h/2
102         
else:
103             
return True
104
105     def is_in_goal(self, position, width):
106         x, y = position
107         
if (y - width <= ZERO and x - width > self.w/2 - self.goal_w/2 and
108                                     x + width < self.w/
2 + self.goal_w/2):
109             
return HOME
110         elif (y + width >= self.h and x - width > self.w/
2 - self.goal_w/2 and
111                                         x + width < self.w/
2 + self.goal_w/2):
112             
return AWAY
113         
else:
114             
return False
115             
116     def get_screen(self):
117         
return self.w, self.h
118     def get_goal_w(self):
119         
return self.goal_w
120         

121 class
Puck(object):
122     def __init__(self, canvas, background):
123         self.background = background
124         self.screen = self.background.get_screen()
125         self.x, self.y = self.screen[
0]/2, self.screen[1]/2
126         self.can, self.w = canvas, self.background.get_goal_w()/
12
127         c, d = rand()
128         self.vx, self.vy =
4*c, 6*d
129         self.a = .
99
130         self.cushion = self.w*
0.25
131         
132         self.puck = PuckManager(canvas, self.w, (self.y, self.x))
133         
134     def update(self):
135         
136         
if self.vx > 0.25: self.vx *= self.a
137         
if self.vy > 0.25: self.vy *= self.a
138         
139         x, y = self.x + self.vx, self.y + self.vy
140         
if not self.background.is_position_valid((x, y), self.w):
141             
if x - self.w < ZERO or x + self.w > self.screen[0]:
142                 self.vx *= -
1
143             
if y - self.w < ZERO or y + self.w > self.screen[1]:
144                 self.vy *= -
1
145             x, y = self.x+self.vx, self.y+self.vy
146             
147         self.x, self.y = x, y
148         self.puck.update((self.x, self.y))
149
150     def hit(self, paddle, moving):
151         x, y = paddle.get_position()
152
153         
if moving:
154             
if (x > self.x - self.cushion and x < self.x + self.cushion or
155                                                     abs(self.vx) > MAX_SPEED):
156                 xpower =
1
157             
else:
158                 xpower =
5 if self.vx < 2 else 2
159             
if (y > self.y - self.cushion and y < self.y + self.cushion or
160                                                     abs(self.vy) > MAX_SPEED):
161                 ypower =
1
162             
else:
163                 ypower =
5 if self.vy < 2 else 2
164         
else:
165             xpower, ypower =
1, 1
166             
167         
if self.x + self.cushion < x:
168             xpower *= -
1
169         
if self.y + self.cushion < y:
170             ypower *= -
1
171         
172         self.vx = abs(self.vx)*xpower
173         self.vy = abs(self.vy)*ypower
174     
175     def __eq__(self, other):
176         
return other == self.puck
177     def in_goal(self):
178         
return self.background.is_in_goal((self.x, self.y), self.w)
179
180 class
Player(object):
181     def __init__(self, master, canvas, background, puck, constraint):
182         self.puck, self.background = puck, background
183         self.constraint, self.v = constraint, PADDLE_SPEED
184         screen = self.background.get_screen()
185         self.x = screen[
0]/2
186         self.y =
60 if self.constraint == UPPER else screen[1] - 50
187
188         self.paddle = Paddle(canvas, self.background.get_goal_w()/
7,
189                                                             (self.x, self.y))
190         self.up, self.down, self.left, self.right = False, False, False, False
191         
192         
if self.constraint == LOWER:
193             master.bind(
'<Up>', self.MoveUp)
194             master.bind(
'<Down>', self.MoveDown)
195             master.bind(
'<KeyRelease-Up>', self.UpRelease)
196             master.bind(
'<KeyRelease-Down>', self.DownRelease)
197             master.bind(
'<Right>', self.MoveRight)
198             master.bind(
'<Left>', self.MoveLeft)
199             master.bind(
'<KeyRelease-Right>', self.RightRelease)
200             master.bind(
'<KeyRelease-Left>', self.LeftRelease)
201         
else:
202             master.bind(
'<w>', self.MoveUp)
203             master.bind(
'<s>', self.MoveDown)
204             master.bind(
'<KeyRelease-w>', self.UpRelease)
205             master.bind(
'<KeyRelease-s>', self.DownRelease)
206             master.bind(
'<d>', self.MoveRight)
207             master.bind(
'<a>', self.MoveLeft)
208             master.bind(
'<KeyRelease-d>', self.RightRelease)
209             master.bind(
'<KeyRelease-a>', self.LeftRelease)
210         
211     def update(self):
212         x, y = self.x, self.y
213         
214         
if self.up: y = self.y - self.v
215         
if self.down: y = self.y + self.v
216         
if self.left: x = self.x - self.v
217         
if self.right: x = self.x + self.v
218         
219         
if self.background.is_position_valid((x, y),
220                                       self.paddle.get_width(), self.constraint):
221             self.x, self.y = x, y
222             self.paddle.update((self.x, self.y))
223         
if self.puck == self.paddle:
224             moving = any((self.up, self.down, self.left, self.right))
225             self.puck.hit(self.paddle, moving)
226     
227     def MoveUp(self, callback=False):
228         self.up = True
229     def MoveDown(self, callback=False):
230         self.down = True
231     def MoveLeft(self, callback=False):
232         self.left = True
233     def MoveRight(self, callback=False):
234         self.right = True
235     def UpRelease(self, callback=False):
236         self.up = False
237     def DownRelease(self, callback=False):
238         self.down = False
239     def LeftRelease(self, callback=False):
240         self.left = False
241     def RightRelease(self, callback=False):
242         self.right = False
243         

244 class
Home(object):
245     def __init__(self, master, screen, score=START_SCORE.copy()):
246         self.frame = tk.Frame(master)
247         self.frame.pack()
248         self.can = tk.Canvas(self.frame)
249         self.can.pack()
250         background = Background(self.can, screen, screen[
0]*0.33)
251         self.puck = Puck(self.can, background)
252         self.p1 = Player(master, self.can, background, self.puck, UPPER)
253         self.p2 = Player(master, self.can, background, self.puck, LOWER)
254         
255         master.bind(
"<Return>", self.reset)
256         master.bind(
"<r>", self.reset)
257         
258         master.title(str_dict(score))
259         
260         self.master, self.screen, self.score = master, screen, score
261         
262         self.update()
263         
264     def reset(self, callback=False):
265         
""" <Return> or <r> key. """
266         
if callback.keycode == 82:
267             self.score = START_SCORE.copy()
268         self.frame.destroy()
269         self.__init__(self.master, self.screen, self.score)
270         
271     def update(self):
272         self.puck.update()
273         self.p1.update()
274         self.p2.update()
275         
if not self.puck.in_goal():
276             self.frame.after(SPEED, self.update)
277         
else:
278             winner = HOME
if self.puck.in_goal() == AWAY else AWAY
279             self.update_score(winner)
280             
281     def update_score(self, winner):
282         self.score[winner] +=
1
283         self.master.title(str_dict(self.score))
284         
if self.score[winner] == MAX_SCORE:
285             self.frame.bell()
286             self.can.create_text(self.screen[
0]/2, self.screen[1]/2, font=FONT,
287                                                      text=
"%s wins!" % winner)
288             self.score = START_SCORE.copy()
289         
else:
290             self.can.create_text(self.screen[
0]/2, self.screen[1]/2, font=FONT,
291                                                  text=
"Point for %s" % winner)
292                                                  
293 def play(screen):
294     root = tk.Tk()
295     Home(root, screen)
296     root.mainloop()
297             

298 if
__name__ == "__main__":
299     
300     screen =
700, 760
301     
302     play(screen)


Gõ tìm kiếm nhanh...